﻿/*
 * Erstellt mit SharpDevelop.
 * Benutzer: Kai Patrick
 * Datum: 29.04.2008
 * Zeit: 15:43
 * 
 * Sie können diese Vorlage unter Extras > Optionen > Codeerstellung > Standardheader ändern.
 */

using System;
using System.Xml.Linq;
using System.Collections.Generic;

namespace Gamadus.Core.Resources
{
	//important: only use value types in derived classes!
	public abstract class ActionParam
	{		
		public virtual string DisplayValue
		{
			get
			{
				return "Unknown";
			}
		}
		public virtual string CodeValue
		{
			get
			{
				return "Unknown";
			}
		}
		public virtual void SetValue(object value)
		{
			
		}
		
//		public ActionParam Clone()
//		{
//			return (ActionParam)this.MemberwiseClone();
//		}
		
		public virtual void WriteXml(XElement xml)
		{
			throw new NotImplementedException();
		}
		
		public virtual void ReadXml(XElement element)
		{
			throw new NotImplementedException();
		}
	}
	
	public class ActionParamColor : ActionParam
	{
		System.Drawing.Color val;
		public override string DisplayValue
		{
			get
			{
				//TODO: format more readable
				return val.ToString();
			}
		}
		public override string CodeValue
		{
			get
			{
				return (val.R+val.G*256+val.B*256*256).ToString();
			}
		}
		
		public override void SetValue(object value)
		{
			if(value is int)
			{
				throw new NotImplementedException();
			}
			if(value is System.Drawing.Color)
			{
				val = (System.Drawing.Color)value;
			}
			else
				throw new ArgumentException("Value must be of type int or Color");
		}
	}
	
	public class ActionParamResource : ActionParam
	{
		
		int val;
		public override string DisplayValue
		{
			get
			{
				//TODO: get resource name
				throw new NotImplementedException();
			}
		}
		
		public override string CodeValue
		{
			get
			{
				return val.ToString();
			}
		}
		
		public override void SetValue(object value)
		{
			if(value is int)
			{
				val = (int)value;
				if(val < 0)
					throw new ArgumentException("Value must be 0 or greater");
			}
			else
				throw new ArgumentException("Value must be of type int");
		}
	}
	
	public class ActionParamEnum : ActionParam
	{
		int val;
		Dictionary<int, string> options = new Dictionary<int, string>();
		
		public ActionParamEnum(Dictionary<int, string> options)
		{
			this.options = options;
		}
		public override string DisplayValue
		{
			get
			{
				return options[val];
			}
		}
		
		public override string CodeValue
		{
			get
			{
				return val.ToString();
			}
		}
		
		public override void SetValue(object value)
		{
			if(value is int)
			{
				val = (int)value;
				if(!options.ContainsKey(val))
					throw new ArgumentException("Value is not in dictionary");
			}
			else
				throw new ArgumentException("Value must be of type int");
		}
	}
	
	public class ActionParamBool : ActionParam
	{
		bool val = false;
		
		public override string DisplayValue
		{
			get
			{
				return val.ToString();
			}
		}
		public override string CodeValue
		{
			get
			{
				return val.ToString().ToLower();
			}
		}
		public override void SetValue(object value)
		{
			if(value is bool)
			{
				val = (bool)value;
			}
			else
				throw new ArgumentException("Value must be of type bool");
		}
	}
	
	public class ActionParamDirection : ActionParam
	{
		[Flags]
		public enum Direction
		{
			East = 1,
			NorthEast = 2,
			North = 4,
			NorthWest = 8,
			West = 16,
			SouthWest = 32,
			South = 64,
			SouthEast = 128,
			Stop = 256
		}
		
		Direction val;
		
		public override string DisplayValue
		{
			get
			{
				return val.ToString();
			}
		}
		public override string CodeValue
		{
			get
			{
				return ((int)val).ToString(System.Globalization.CultureInfo.InvariantCulture);
			}
		}
		public override void SetValue(object value)
		{
			if(value is int)
			{
				int i = (int)value;
				if(i < 0 || i > 511)
					throw new ArgumentException("Integer value must be between 0 and 511");
				val = (Direction)i;
			}
			else if(value is Direction)
			{
				val = (Direction)value;
			}
			else
				throw new ArgumentException("Value must be of type int or Direction");
		}
	}
	
	public class ActionParamAppliesTo : ActionParam
	{
		int val;
		
		public override string DisplayValue
		{
			get
			{
				switch(val)
				{
					case -2:
						return "Other";
					case -1:
						return "Self";
					default:
						//TODO: get name of object resource
						throw new NotImplementedException();
				}
			}
		}
		public override string CodeValue
		{
			get
			{
				return val.ToString(System.Globalization.CultureInfo.InvariantCulture);
			}
		}
		public override void SetValue(object value)
		{
			if(value is int)
			{
				val = (int)value;
				if(val < -2)
					throw new ArgumentException("Value must not be smaller than -2");
			}
			else
				throw new ArgumentException("Value must be of type int");
		}
	}
	
	public class ActionParamDouble : ActionParam
	{
		double val;
		
		public override string DisplayValue
		{
			get
			{
				return val.ToString(System.Globalization.CultureInfo.InvariantCulture);
			}
		}
		public override string CodeValue
		{
			get
			{
				return val.ToString(System.Globalization.CultureInfo.InvariantCulture);
			}
		}
		public override void SetValue(object value)
		{
			if(value is double)
				val = (double)value;
			else
				throw new ArgumentException("Value must be of type double");
		}
	}
	
	public class ActionParamString : ActionParam
	{
		string val = "";
		
		public override string DisplayValue
		{
			get
			{
				return val;
			}
		}
		public override string CodeValue
		{
			get
			{
				return val;
			}
		}
		public override void SetValue(object value)
		{
			if(value is string)
				val = value as string;
			else
				throw new ArgumentException("Value must be of type string");
		}
		
//		public override void WriteXml(XmlTextWriter xml)
//		{
//			xml.WriteString(val);
//		}
//		
//		public override void ReadXml(XmlElement element)
//		{
//			val = element.InnerText;
//		}
	}
	
	public class ActionParamPrototype
	{
		System.Type paramType;
		protected object defaultValue;
		public ActionParamPrototype(System.Type paramType) : this(paramType, null)
		{
			
		}
		
		public virtual ActionParam Create()
		{
			ActionParam param = (ActionParam)System.Activator.CreateInstance(paramType);
			if(defaultValue != null)
				param.SetValue(defaultValue);
			return param;
		}
		
		public ActionParamPrototype(System.Type paramType, object defaultValue)
		{
			if(!paramType.IsSubclassOf(typeof(ActionParam)))
				throw new ArgumentException("Parameter Type is not a subclass of ActionParam");
			this.paramType = paramType;
			this.defaultValue = defaultValue;
		}
	}
	
	public class ActionParamEnumPrototype : ActionParamPrototype
	{
		Dictionary<int, string> options = new Dictionary<int, string>();
		public ActionParamEnumPrototype() : this(null)
		{}
		
		public ActionParamEnumPrototype(object defaultValue) : base(typeof(ActionParamEnum),defaultValue)
		{
			
		}
		
		public override ActionParam Create()
		{
			ActionParamEnum param = new ActionParamEnum(options);
			param.SetValue(defaultValue);
			return param;
		}
		
		public void AddOption(int value, string name)
		{
			options.Add(value, name);
		}
	}
}
